#include <iostream>
#include <vector>
#include <algorithm>

//auto 的使用参看：https://blog.csdn.net/weixin_40335501/article/details/134812261
int main(int argc, char *argv[])
{
    int a = 10, b = 20;
    //lambda 表达式类型1 [捕获列表](参数列表)->返回值类型{函数体}; 
    auto f1 = [a, b](int x, int y)->int{return a+b+x+y;};
    int sum1 = f1(30,40);
    std::cout << "sum1 = " << sum1 << std::endl; //值为10+20+30+40=100

    //lambda 表达式类型2 lambda 表达式类型1 [捕获列表](参数列表){函数体}; 
    //编译器并不是总能推断出返回值类型，如果编译器推断不出来，它就会报错，这时我们需要显式给出具体的返回值类型。
    auto f2 = [a, b](int x, int y){return a+b+x+y;};
    int sum2 = f2(30,40);
    std::cout << "sum2 = " << sum2 << std::endl; //值为10+20+30+40=100

    //lambda 表达式类型3 [捕获列表]{函数体};
    auto f3 = [a, b]{return a+b;};
    int sum3 = f3();
    std::cout << "sum3 = " << sum3 << std::endl; //值为10+20=30

    //lambda 表达式类型4 []{函数体};

    auto f4 = []{return 1+2;};
    int sum4 = f4();
    std::cout << "sum4 = " << sum4 << std::endl; //值为1+2=3

    // lambda 表达式类型5
    auto f5 = []{}; //无参，无捕获，空函数体 合法
    f5(); //什么都不做

    // 值捕获
    // auto f6 = [a,b](){a++; b++;}; //错误 值捕获，不能修改a、b的值
    auto f6 = [a,b](){return a+b;};
    int sum6 = f6();
    std::cout << "sum6 = " << sum6 << std::endl; //值为10+20=30

    auto f7 = [=](){return a+b;}; //捕获当前作用域的所有变量a和b
    int sum7 = f7();
    std::cout << "sum7 = " << sum7 << std::endl; //值为10+20=30


    //引用捕获
    auto f8 = [&a,&b](){a++; b++;};
    f8();
    std::cout << "a = " << a << std::endl; //值为11 f8()中a++了
    std::cout << "b = " << b << std::endl; //值为21 f8()中b++了
    
    //混合捕获
    auto f9 = [a,&b](){b++; return a+b;};
    int sum9 = f9();
    std::cout << "b = " << b << std::endl; //值为22
    std::cout << "sum9 = " << sum9 << std::endl; //值为33


    // Lambda表达式的限定符
    int c = 10;
    // auto f10 = [a](){a++;}; //未用mutable修饰,不能修改按值捕获的c的值
    auto f10 = [c]()mutable{c++;};
    f10();
    std::cout << "c = " << c << std::endl; //值仍为10. mutable不能修改表达式外部的c变量值

    std::vector<int> v;
    v.push_back(2);
    v.push_back(1);
    v.push_back(3);
    v.push_back(9);
    v.push_back(7);
    // using lambda as compare function
    std::sort(v.begin(), v.end(), [](const int &a, const int &b)->bool{return a > b;});
    for (int item : v)
    {
        std::cout << "item = " << item <<std::endl; //9 7 3 2 1
    }

	return 0;
}